//START DEFINE
#define LED_D4 12
#define LED_D5 13
#define BAUD_RATE 115200

#define MAC_ADDR_BYTE_LENGTH 6
#define MAC_HEX_CHAR_LENGTH MAC_ADDR_BYTE_LENGTH * 2 + 1

#include "driver/uart.h"
#include "esp_mac.h"
#include <Arduino.h>

#include <BLEServer.h>
#include <BLEService.h>
#include <BLE2902.h>
#include <BLEDevice.h>  // 引入相关库

//ESP32作为服务端，数据流向ESP32的视为上传，从ESP32读取的视为下载
#define SERVICE_UUID "0000FFE0-0000-1000-8000-00805F9B34FB"
#define DOWN_CHARACTERISTIC_UUID "0000FFE1-0000-1000-8000-00805F9B34FB"
#define UP_CHARACTERISTIC_UUID "0000FFE2-0000-1000-8000-00805F9B34FB"

#define FLAG_FRAME_BOUNDARY 0x7F //帧边界
#define FLAG_FRAME_ESCAPING 0x7D //转义
//END DEFINE

//GLOBAL
//BLE
BLECharacteristic* upCharacteristic;
BLECharacteristic* downCharacteristic;

u_int8_t* buffer;
int currentBufferIndex; //当前缓冲区写到哪里

//buffer status


int counter = 0;

//将字节数据转换为16进制
void to_hex(char* dest, size_t dest_len, const uint8_t* values, size_t val_len) {
  static const char hex_table[] = "0123456789ABCDEF";
  if (dest_len < (val_len * 2 + 1)) /* check that dest is large enough */
    return;
  while (val_len--) {
    /* shift down the top nibble and pick a char from the hex_table */
    *dest++ = hex_table[*values >> 4];
    /* extract the bottom nibble and pick a char from the hex_table */
    *dest++ = hex_table[*values++ & 0xF];
  }
  *dest = 0;
  return;
}

//通过芯片蓝牙MAC地址生成蓝牙
char* btNameByDeviceAddress() {
  //读取MAC地址
  u_int8_t* mac_array = new u_int8_t[MAC_ADDR_BYTE_LENGTH];
  esp_read_mac(mac_array, ESP_MAC_BT);

  //将MAC地址转为HEX
  char* mac_hex_array = new char[MAC_HEX_CHAR_LENGTH];
  to_hex(mac_hex_array, MAC_HEX_CHAR_LENGTH, mac_array, MAC_ADDR_BYTE_LENGTH);

  String address = String("ESP32-");
  address.concat(mac_hex_array, MAC_HEX_CHAR_LENGTH);
  int len = address.length() + 1;
  char* address_char_array = new char[len];
  address.toCharArray(address_char_array, len - 1, 0);
  return address_char_array;
}

class MyCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    Serial.write("con");
  };

  void onDisconnect(BLEServer* pServer) {
    Serial.write("discon");
    BLEDevice::startAdvertising();  //蓝牙断开后，重新开始广播
  };
};

class CPPBLECharacteristicCallbacks : public BLECharacteristicCallbacks {
  void onRead(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) {
    Serial.write("onRead");
  };

  void onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) {
    //浏览器端向ESP32写入数据
    String uuidStr = pCharacteristic->getUUID().toString();
    Serial.print("onW");
    Serial.print(uuidStr);
    Serial.println("\r\n");
    uint8_t* data = pCharacteristic->getData();
    size_t size = pCharacteristic->getLength();
    Serial.println("\r\n SIZE:");
    Serial.println(size);
    Serial.println("\r\n");
    size_t hexLength = size * 2 + 1;
    char* hexChar = new char[hexLength];
    to_hex(hexChar, hexLength, data, size);
    Serial.write(hexChar);
  };

  void onNotify(BLECharacteristic* pCharacteristic) {
    Serial.write("onN");
  };

  void onStatus(BLECharacteristic* pCharacteristic, Status status, uint32_t code) {
    switch (status) {
      case SUCCESS_INDICATE:
        Serial.print("SUCCESS_INDICATE");
        break;
      case SUCCESS_NOTIFY:
        Serial.print("SUCCESS_NOTIFY");
        break;
      case ERROR_INDICATE_DISABLED:
        Serial.print("ERROR_INDICATE_DISABLED");
        break;
      case ERROR_NOTIFY_DISABLED:
        Serial.print("ERROR_NOTIFY_DISABLED");
        break;
      case ERROR_GATT:
        Serial.print("ERROR_GATT");
        break;
      case ERROR_NO_CLIENT:
        Serial.print("ERROR_NO_CLIENT");
        break;
      case ERROR_INDICATE_TIMEOUT:
        Serial.print("ERROR_INDICATE_TIMEOUT");
        break;
      case ERROR_INDICATE_FAILURE:
        Serial.print("ERROR_INDICATE_FAILURE");
        break;
      default:
        Serial.print("UNKNOWN_STATUS");
        break;
    }
  };
};

void taskReadFromSerial(void* pvParameters) {
  for (;;) {
    int size = Serial.available();
    if (Serial.available() > 0) {
      u_int8_t* buffer = new u_int8_t[size];
      if (size != -1) {
        Serial.read(buffer, size);  //u_int8_t | -1
        // Serial.write(buffer, size);
        //downCharacteristic->setValue(c);
        for(int i = 0; i < size; ++i) {
          u_int8_t byte = buffer[i];
          switch (byte) {
            case: FLAG_FRAME_BOUNDARY
              //帧分节符
              break;
            case: FLAG_FRAME_BOUNDARY
              //帧分节符
              break;
          }
        }
      }
    }
    vTaskDelay(250 / portTICK_PERIOD_MS);  // 延迟250毫秒
  }
}

void setup() {
  Serial.begin(BAUD_RATE);  //初始化串口通信

  //初始化IO
  pinMode(LED_D4, OUTPUT);
  pinMode(LED_D5, OUTPUT);

  //初始化蓝牙，广播名称为ESP32-MAC
  char* deviceNameWithMac = btNameByDeviceAddress();
  BLEDevice::init(deviceNameWithMac);
  free(deviceNameWithMac);

  //初始化Server和Callback
  BLEServer* pServ = BLEDevice::createServer();
  pServ->setCallbacks(new MyCallbacks());

  BLEService* pService = pServ->createService(SERVICE_UUID);
  upCharacteristic = pService->createCharacteristic(
    UP_CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_INDICATE | BLECharacteristic::PROPERTY_NOTIFY);
  upCharacteristic->setCallbacks(new CPPBLECharacteristicCallbacks());
  upCharacteristic->addDescriptor(new BLE2902());
  upCharacteristic->setNotifyProperty(true);

  downCharacteristic = pService->createCharacteristic(
    DOWN_CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_INDICATE | BLECharacteristic::PROPERTY_NOTIFY);
  downCharacteristic->setCallbacks(new CPPBLECharacteristicCallbacks());
  downCharacteristic->addDescriptor(new BLE2902());
  downCharacteristic->setNotifyProperty(true);

  pService->start();
  // BLEDevice::startAdvertising();             // 开启Advertising广播
  // serv->setCallbacks(new MyCallbacks());

  //启动服务和广播，以便其他BLE设备找到此 BLE 设备
  BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();  //BLE广播
  pAdvertising->addServiceUUID(SERVICE_UUID);                  //广播添加服务 UUID
  pAdvertising->setScanResponse(true);                         //广播扫描响应
  pAdvertising->setMinPreferred(0x06);                         //广播设置最小首选
  pAdvertising->setMinPreferred(0x12);                         //广播设置最小首选
  BLEDevice::startAdvertising();                               //BLE 设备启动广播，特征已经定义，可以在手机中读取它


  //--------创建串口读取任务
  xTaskCreate(taskReadFromSerial, "taskReadFromSerial", 512, NULL, 2, NULL);
}

void loop() {
  digitalWrite(LED_D4, LOW);
  // digitalWrite(LED_D5, HIGH);
  delay(2000);
  digitalWrite(LED_D4, HIGH);
  // digitalWrite(LED_D5, LOW);
  delay(100);
  // Serial.write("TICK\r\n");
  if (downCharacteristic != nullptr) {
    // pCharacteristic->notify();
    downCharacteristic->setValue("counter is = " + String(++counter) + "1+2++3+++4++++5+++++6++++++7+++++++8++++++++9+++++++++10++++++++++11+++++++++++12++++++++++++13+++++++++++++14++++++++++++++15+++++++++++++++16++++++++++++++++17+++++++++++++++++18++++++++++++++++++19+++++++++++++++++++20++++++++++++++++++++21+++++++++++++++++++++22++++++++++++++++++++++23+++++++++++++++++++++++24++++++++++++++++++++++++25+++++++++++++++++++++++++26++++++++++++++++++++++");
    // pCharacteristic->notify();
  }
}
